import { Byte } from '../../api/io/Byte';
import { HashMap } from '../../api/struct/HashMap';
import { ArenaBattleHistory } from './ArenaBattleHistory';
import { ArenaRankPlayer } from './ArenaRankPlayer';
import { ArenaRankReward } from './ArenaRankReward';
import { ITimer } from '../../api/timer/ITimer';
import { IAsync } from '../../api/event/IAsync';
import { MathUtils } from '../../api/math/MathUtils';



/**竞技场属性枚举*/
export const enum E_Arena {
	/**参与竞技*/
	JOIN = 0,
	/**参与的竞技场开启时间*/
	JOIN_RANK_START_TIME = 1,
	/**积分*/
	ARENA_SCORE = 2,
	/**本赛季主动挑战次数*/
	CHALLENGE_ACTIVE = 3,
	/**本赛季被动挑战次数*/
	CHALLENGE_NATIVE = 4,
	/**今日第一次处理时间*/
	DAILY_FIRST_TIME = 5,
	/**今日挑战次数*/
	DAILY_CHALLENGE = 6,
	/**今日卷轴已购买数*/
	DAILY_REEL_BUY = 7,
	/**宠物站位<id, 位置>*/
	PET = 8,
	/**挑战记录<赛季时间, 记录>*/
	HISTORY = 9,
	/**上一次手动刷新时间*/
	LAST_REFRESH_TIME = 10,
	/**可挑战的玩家<player_id, >*/
	ENEMY = 11,
	/**排名奖励<赛季时间，奖励内容>*/
	RANK_REWARD = 12,
	/**排名*/
	RANK_INDEX = 13,
	/**枚举数量*/
	EnumCount = 14
}


/**竞技场*/
export class Arena {
	/**事件ID*/
	public static readonly EVENT_ID = 'STRUCT_DATA_ARENA_EVENT_ID';
	/**整体更新事件ID（部分只需要监听整体变化）*/
	public static readonly TOTAL_EVENT_ID = 'STRUCT_DATA_ARENA_TOTAL_EVENT_ID';
	/**缓存池*/
	private static POOL: Arena[] = [];

	/**创建入口*/
	public static create(json?: string): Arena {
		const c = this.POOL.pop() || new Arena();
		c._destroyed = false;
		c.resetProperty();
		if (json) {
			c.parse(json);
		}
		return c;
	}


	/**已释放*/
	protected _destroyed = false;
	/**参与竞技*/
	protected _join: boolean;
	/**参与的竞技场开启时间 (long)*/
	protected _joinRankStartTime: number;
	/**积分 (long)*/
	protected _arenaScore: number;
	/**本赛季主动挑战次数 (uint16)*/
	protected _challengeActive: number;
	/**本赛季被动挑战次数 (uint16)*/
	protected _challengeNative: number;
	/**今日第一次处理时间 (long)*/
	protected _dailyFirstTime: number;
	/**今日挑战次数 (uint16)*/
	protected _dailyChallenge: number;
	/**今日卷轴已购买数 (uint16)*/
	protected _dailyReelBuy: number;
	/**宠物站位<id, 位置> (uint32, int8)*/
	protected _pet: HashMap<number, number> = null;
	/**挑战记录<赛季时间, 记录>*/
	protected _history: HashMap<number, ArenaBattleHistory> = null;
	/**上一次手动刷新时间 (long)*/
	protected _lastRefreshTime: number;
	/**可挑战的玩家<player_id, >*/
	protected _enemy: HashMap<number, ArenaRankPlayer> = null;
	/**排名奖励<赛季时间，奖励内容>*/
	protected _rankReward: HashMap<number, ArenaRankReward> = null;
	/**排名 (int32)*/
	protected _rankIndex: number;


	/**构建函数-私有，防止外部创建*/
	private constructor() {
	}


	/**释放*/
	public destroy(): void {
		if (this._destroyed) {
			return;
		}
		this._destroyed = true;
		this.resetProperty(true);
		if (Arena.POOL.indexOf(this) === -1) {
			Arena.POOL.push(this);
		}
	}

	/**参与竞技*/
	public get join() {
		return this._join;
	}


	/**参与竞技*/
	public set join(v: boolean) {
		this._join = v;
	}


	/**参与的竞技场开启时间*/
	public get joinRankStartTime() {
		return this._joinRankStartTime;
	}


	/**参与的竞技场开启时间*/
	public set joinRankStartTime(v: number) {
		this._joinRankStartTime = v;
	}


	/**积分*/
	public get arenaScore() {
		return this._arenaScore;
	}


	/**积分*/
	public set arenaScore(v: number) {
		this._arenaScore = v;
	}


	/**本赛季主动挑战次数*/
	public get challengeActive() {
		return this._challengeActive;
	}


	/**本赛季主动挑战次数*/
	public set challengeActive(v: number) {
		this._challengeActive = v;
	}


	/**本赛季被动挑战次数*/
	public get challengeNative() {
		return this._challengeNative;
	}


	/**本赛季被动挑战次数*/
	public set challengeNative(v: number) {
		this._challengeNative = v;
	}


	/**今日第一次处理时间*/
	public get dailyFirstTime() {
		return this._dailyFirstTime;
	}


	/**今日第一次处理时间*/
	public set dailyFirstTime(v: number) {
		this._dailyFirstTime = v;
	}


	/**今日挑战次数*/
	public get dailyChallenge() {
		return this._dailyChallenge;
	}


	/**今日挑战次数*/
	public set dailyChallenge(v: number) {
		this._dailyChallenge = v;
	}


	/**今日卷轴已购买数*/
	public get dailyReelBuy() {
		return this._dailyReelBuy;
	}


	/**今日卷轴已购买数*/
	public set dailyReelBuy(v: number) {
		this._dailyReelBuy = v;
	}


	/**设置宠物站位<id, 位置>*/
	public putPet(k: number, v: number): number {
		const ov = this._pet.put(k, v);
		return ov || 0;
	}


	/**获取宠物站位<id, 位置>*/
	public getPet(k: number) {
		return this._pet.get(k) || 0;
	}


	/**删除宠物站位<id, 位置>*/
	public removePet(k: number): number {
		const ov = this._pet.remove(k);
		return ov || 0;
	}


	/**获取宠物站位<id, 位置>映射表-键值(外部改变将导致出错，只能用于遍历)*/
	public getPetKeys(): number[] {
		return this._pet.getKeys();
	}


	/**获取宠物站位<id, 位置>映射表-值(外部改变将导致出错，只能用于遍历)*/
	public getPetValues(): number[] {
		return this._pet.getValues();
	}


	/**清空宠物站位<id, 位置>映射表*/
	public clearPetMap(): void {
		this._pet.clear();
	}


	/**设置挑战记录<赛季时间, 记录>*/
	public putHistory(k: number, v: ArenaBattleHistory): ArenaBattleHistory {
		const ov = this._history.put(k, v);
		return ov;
	}


	/**获取挑战记录<赛季时间, 记录>*/
	public getHistory(k: number) {
		return this._history.get(k);
	}


	/**删除挑战记录<赛季时间, 记录>*/
	public removeHistory(k: number, autoDestroy = false): ArenaBattleHistory {
		const ov = this._history.remove(k);
		if (autoDestroy && ov) {
			ov.destroy();
		}
		return ov;
	}


	/**获取挑战记录<赛季时间, 记录>映射表-键值(外部改变将导致出错，只能用于遍历)*/
	public getHistoryKeys(): number[] {
		return this._history.getKeys();
	}


	/**获取挑战记录<赛季时间, 记录>映射表-值(外部改变将导致出错，只能用于遍历)*/
	public getHistoryValues(): ArenaBattleHistory[] {
		return this._history.getValues();
	}


	/**清空挑战记录<赛季时间, 记录>映射表*/
	public clearHistoryMap(autoDestroy = false): void {
		const ks = this._history.getKeys();
		for (let i = ks.length - 1; i >= 0; i--) {
			this.removeHistory(ks[i], autoDestroy);
		}
	}


	/**上一次手动刷新时间*/
	public get lastRefreshTime() {
		return this._lastRefreshTime;
	}


	/**上一次手动刷新时间*/
	public set lastRefreshTime(v: number) {
		this._lastRefreshTime = v;
	}


	/**设置可挑战的玩家<player_id, >*/
	public putEnemy(k: number, v: ArenaRankPlayer): ArenaRankPlayer {
		const ov = this._enemy.put(k, v);
		return ov;
	}


	/**获取可挑战的玩家<player_id, >*/
	public getEnemy(k: number) {
		return this._enemy.get(k);
	}


	/**删除可挑战的玩家<player_id, >*/
	public removeEnemy(k: number, autoDestroy = false): ArenaRankPlayer {
		const ov = this._enemy.remove(k);
		if (autoDestroy && ov) {
			ov.destroy();
		}
		return ov;
	}


	/**获取可挑战的玩家<player_id, >映射表-键值(外部改变将导致出错，只能用于遍历)*/
	public getEnemyKeys(): number[] {
		return this._enemy.getKeys();
	}


	/**获取可挑战的玩家<player_id, >映射表-值(外部改变将导致出错，只能用于遍历)*/
	public getEnemyValues(): ArenaRankPlayer[] {
		return this._enemy.getValues();
	}


	/**清空可挑战的玩家<player_id, >映射表*/
	public clearEnemyMap(autoDestroy = false): void {
		const ks = this._enemy.getKeys();
		for (let i = ks.length - 1; i >= 0; i--) {
			this.removeEnemy(ks[i], autoDestroy);
		}
	}


	/**设置排名奖励<赛季时间，奖励内容>*/
	public putRankReward(k: number, v: ArenaRankReward): ArenaRankReward {
		const ov = this._rankReward.put(k, v);
		return ov;
	}


	/**获取排名奖励<赛季时间，奖励内容>*/
	public getRankReward(k: number) {
		return this._rankReward.get(k);
	}


	/**删除排名奖励<赛季时间，奖励内容>*/
	public removeRankReward(k: number, autoDestroy = false): ArenaRankReward {
		const ov = this._rankReward.remove(k);
		if (autoDestroy && ov) {
			ov.destroy();
		}
		return ov;
	}


	/**获取排名奖励<赛季时间，奖励内容>映射表-键值(外部改变将导致出错，只能用于遍历)*/
	public getRankRewardKeys(): number[] {
		return this._rankReward.getKeys();
	}


	/**获取排名奖励<赛季时间，奖励内容>映射表-值(外部改变将导致出错，只能用于遍历)*/
	public getRankRewardValues(): ArenaRankReward[] {
		return this._rankReward.getValues();
	}


	/**清空排名奖励<赛季时间，奖励内容>映射表*/
	public clearRankRewardMap(autoDestroy = false): void {
		const ks = this._rankReward.getKeys();
		for (let i = ks.length - 1; i >= 0; i--) {
			this.removeRankReward(ks[i], autoDestroy);
		}
	}


	/**排名*/
	public get rankIndex() {
		return this._rankIndex;
	}


	/**排名*/
	public set rankIndex(v: number) {
		this._rankIndex = v;
	}



	/**通过枚举获取值*/
	public getV(k: E_Arena): any {
		switch (k) {
			case E_Arena.JOIN: return this._join;
			case E_Arena.JOIN_RANK_START_TIME: return this._joinRankStartTime;
			case E_Arena.ARENA_SCORE: return this._arenaScore;
			case E_Arena.CHALLENGE_ACTIVE: return this._challengeActive;
			case E_Arena.CHALLENGE_NATIVE: return this._challengeNative;
			case E_Arena.DAILY_FIRST_TIME: return this._dailyFirstTime;
			case E_Arena.DAILY_CHALLENGE: return this._dailyChallenge;
			case E_Arena.DAILY_REEL_BUY: return this._dailyReelBuy;
			case E_Arena.PET: return this._pet;
			case E_Arena.HISTORY: return this._history;
			case E_Arena.LAST_REFRESH_TIME: return this._lastRefreshTime;
			case E_Arena.ENEMY: return this._enemy;
			case E_Arena.RANK_REWARD: return this._rankReward;
			case E_Arena.RANK_INDEX: return this._rankIndex;
			default: return null;
		}
	}


	/**通过枚举设置值*/
	public setV(k: E_Arena, v: any): void {
		switch (k) {
			case E_Arena.JOIN: this._join = v; break;
			case E_Arena.JOIN_RANK_START_TIME: this._joinRankStartTime = v; break;
			case E_Arena.ARENA_SCORE: this._arenaScore = v; break;
			case E_Arena.CHALLENGE_ACTIVE: this._challengeActive = v; break;
			case E_Arena.CHALLENGE_NATIVE: this._challengeNative = v; break;
			case E_Arena.DAILY_FIRST_TIME: this._dailyFirstTime = v; break;
			case E_Arena.DAILY_CHALLENGE: this._dailyChallenge = v; break;
			case E_Arena.DAILY_REEL_BUY: this._dailyReelBuy = v; break;
			case E_Arena.PET: this._pet = v; break;
			case E_Arena.HISTORY: this._history = v; break;
			case E_Arena.LAST_REFRESH_TIME: this._lastRefreshTime = v; break;
			case E_Arena.ENEMY: this._enemy = v; break;
			case E_Arena.RANK_REWARD: this._rankReward = v; break;
			case E_Arena.RANK_INDEX: this._rankIndex = v; break;
			default: break;
		}
	}


	/**初始化*/
	public resetProperty(fromDestroy = false): void {
		//参与竞技
		this._join = false;
		//参与的竞技场开启时间
		this._joinRankStartTime = 0;
		//积分
		this._arenaScore = 0;
		//本赛季主动挑战次数
		this._challengeActive = 0;
		//本赛季被动挑战次数
		this._challengeNative = 0;
		//今日第一次处理时间
		this._dailyFirstTime = 0;
		//今日挑战次数
		this._dailyChallenge = 0;
		//今日卷轴已购买数
		this._dailyReelBuy = 0;
		//宠物站位<id, 位置>
		if (this._pet) {
			this._pet.clear();
		}
		else {
			this._pet = new HashMap<number, number>();
		}
		//挑战记录<赛季时间, 记录>
		if (this._history) {
			const list = this._history.getValues();
			for (let i = 0, len = list.length; i < len; i++) {
				list[i].destroy();
			}
			this._history.clear();
		}
		else {
			this._history = new HashMap<number, ArenaBattleHistory>();
		}
		//上一次手动刷新时间
		this._lastRefreshTime = 0;
		//可挑战的玩家<player_id, >
		if (this._enemy) {
			const list = this._enemy.getValues();
			for (let i = 0, len = list.length; i < len; i++) {
				list[i].destroy();
			}
			this._enemy.clear();
		}
		else {
			this._enemy = new HashMap<number, ArenaRankPlayer>();
		}
		//排名奖励<赛季时间，奖励内容>
		if (this._rankReward) {
			const list = this._rankReward.getValues();
			for (let i = 0, len = list.length; i < len; i++) {
				list[i].destroy();
			}
			this._rankReward.clear();
		}
		else {
			this._rankReward = new HashMap<number, ArenaRankReward>();
		}
		//排名
		this._rankIndex = 0;
	}


	/**序列化*/
	public stringify(toString: boolean): string | any {
		const json: any = {};
		if (this._join) {
			json.join = this._join;
		}
		if (this._joinRankStartTime) {
			json.joinRankStartTime = this._joinRankStartTime;
		}
		if (this._arenaScore) {
			json.arenaScore = this._arenaScore;
		}
		if (this._challengeActive) {
			json.challengeActive = this._challengeActive;
		}
		if (this._challengeNative) {
			json.challengeNative = this._challengeNative;
		}
		if (this._dailyFirstTime) {
			json.dailyFirstTime = this._dailyFirstTime;
		}
		if (this._dailyChallenge) {
			json.dailyChallenge = this._dailyChallenge;
		}
		if (this._dailyReelBuy) {
			json.dailyReelBuy = this._dailyReelBuy;
		}
		if (this._pet.size() > 0) {
			const ks = this._pet.getKeys();
			const vs = this._pet.getValues();
			json.pet = [ks, vs];
		}
		if (this._history.size() > 0) {
			const ks = this._history.getKeys();
			const vs = this._history.getValues();
			const list: string[] = [];
			for (let i = 0, len = vs.length; i < len; i++) {
				list[i] = vs[i].stringify(false);
			}
			json.history = [ks, list];
		}
		if (this._lastRefreshTime) {
			json.lastRefreshTime = this._lastRefreshTime;
		}
		if (this._enemy.size() > 0) {
			const ks = this._enemy.getKeys();
			const vs = this._enemy.getValues();
			const list: string[] = [];
			for (let i = 0, len = vs.length; i < len; i++) {
				list[i] = vs[i].stringify(false);
			}
			json.enemy = [ks, list];
		}
		if (this._rankReward.size() > 0) {
			const ks = this._rankReward.getKeys();
			const vs = this._rankReward.getValues();
			const list: string[] = [];
			for (let i = 0, len = vs.length; i < len; i++) {
				list[i] = vs[i].stringify(false);
			}
			json.rankReward = [ks, list];
		}
		if (this._rankIndex) {
			json.rankIndex = this._rankIndex;
		}

		return toString ? JSON.stringify(json) : json;
	}


	/**反序列化*/
	public parse(jsonv: string | any): this {
		this.resetProperty();
		if (!jsonv) {
			return this;
		}
		const json = typeof (jsonv) === 'string' ? JSON.parse(jsonv) : jsonv;
		if (json.join) {
			this._join = json.join;
		}
		if (json.joinRankStartTime) {
			this._joinRankStartTime = json.joinRankStartTime;
		}
		if (json.arenaScore) {
			this._arenaScore = json.arenaScore;
		}
		if (json.challengeActive) {
			this._challengeActive = json.challengeActive;
		}
		if (json.challengeNative) {
			this._challengeNative = json.challengeNative;
		}
		if (json.dailyFirstTime) {
			this._dailyFirstTime = json.dailyFirstTime;
		}
		if (json.dailyChallenge) {
			this._dailyChallenge = json.dailyChallenge;
		}
		if (json.dailyReelBuy) {
			this._dailyReelBuy = json.dailyReelBuy;
		}
		if (json.pet) {
			const ks: number[] = json.pet[0];
			const vs: number[] = json.pet[1];
			if (ks && vs && ks.length === vs.length) {	//json
				this._pet.setKeyAndValueList(ks, vs);
			}
			else if (json.pet.getKeys && json.pet.getValues) {	//结构体
				const ks2 = json.pet.getKeys();
				const vs2 = json.pet.getValues();
				if (ks2 && vs2 && ks2.length === vs2.length) {
					for (let i = 0, len = vs2.length; i < len; i++) {
						this._pet.put(ks2[i], vs2[i]);	//重新添加，防止数据公用后被释放导致bug
					}
				}
			}
		}
		if (json.history) {
			const ks: number[] = json.history[0] || (json.history.getKeys ? json.history.getKeys() : null);	//对象可能是json或者结构体
			const vs: string[] = json.history[1] || (json.history.getValues ? json.history.getValues() : null);
			if (ks && vs && ks.length === vs.length) {
				for (let i = 0, len = vs.length; i < len; i++) {
					this._history.put(ks[i], ArenaBattleHistory.create(vs[i]));
				}
			}
		}
		if (json.lastRefreshTime) {
			this._lastRefreshTime = json.lastRefreshTime;
		}
		if (json.enemy) {
			const ks: number[] = json.enemy[0] || (json.enemy.getKeys ? json.enemy.getKeys() : null);	//对象可能是json或者结构体
			const vs: string[] = json.enemy[1] || (json.enemy.getValues ? json.enemy.getValues() : null);
			if (ks && vs && ks.length === vs.length) {
				for (let i = 0, len = vs.length; i < len; i++) {
					this._enemy.put(ks[i], ArenaRankPlayer.create(vs[i]));
				}
			}
		}
		if (json.rankReward) {
			const ks: number[] = json.rankReward[0] || (json.rankReward.getKeys ? json.rankReward.getKeys() : null);	//对象可能是json或者结构体
			const vs: string[] = json.rankReward[1] || (json.rankReward.getValues ? json.rankReward.getValues() : null);
			if (ks && vs && ks.length === vs.length) {
				for (let i = 0, len = vs.length; i < len; i++) {
					this._rankReward.put(ks[i], ArenaRankReward.create(vs[i]));
				}
			}
		}
		if (json.rankIndex) {
			this._rankIndex = json.rankIndex;
		}
		return this;
	}


	/**序列化-二进制*/
	public toBytes(byte: Byte): void {
		if (!byte) {
			return;
		}
		byte.writeBool(this._join);
		byte.writeLongNumber(this._joinRankStartTime);
		byte.writeLongNumber(this._arenaScore);
		byte.writeUint16(this._challengeActive);
		byte.writeUint16(this._challengeNative);
		byte.writeLongNumber(this._dailyFirstTime);
		byte.writeUint16(this._dailyChallenge);
		byte.writeUint16(this._dailyReelBuy);
		//宠物站位<id, 位置>
		{
			const ks = this._pet.getKeys();
			const vs = this._pet.getValues();
			const len = ks.length;
			byte.writeUint16(len);
			for (let i = 0; i < len; i++) {
				byte.writeUint32(ks[i]);
				byte.writeInt8(vs[i]);
			}
		}
		//挑战记录<赛季时间, 记录>
		{
			const ks = this._history.getKeys();
			const vs = this._history.getValues();
			const len = ks.length;
			byte.writeUint16(len);
			for (let i = 0; i < len; i++) {
				byte.writeLongNumber(ks[i]);
				vs[i].toBytes(byte);
			}
		}
		byte.writeLongNumber(this._lastRefreshTime);
		//可挑战的玩家<player_id, >
		{
			const ks = this._enemy.getKeys();
			const vs = this._enemy.getValues();
			const len = ks.length;
			byte.writeUint16(len);
			for (let i = 0; i < len; i++) {
				byte.writeLongNumber(ks[i]);
				vs[i].toBytes(byte);
			}
		}
		//排名奖励<赛季时间，奖励内容>
		{
			const ks = this._rankReward.getKeys();
			const vs = this._rankReward.getValues();
			const len = ks.length;
			byte.writeUint16(len);
			for (let i = 0; i < len; i++) {
				byte.writeLongNumber(ks[i]);
				vs[i].toBytes(byte);
			}
		}
		byte.writeInt32(this._rankIndex);
	}


	/**反序列化-二进制*/
	public fromBytes(byte: Byte): this {
		this.resetProperty();
		if (!byte) {
			return;
		}
		this._join = byte.readBool();
		this._joinRankStartTime = byte.readLongNumber();
		this._arenaScore = byte.readLongNumber();
		this._challengeActive = byte.readUint16();
		this._challengeNative = byte.readUint16();
		this._dailyFirstTime = byte.readLongNumber();
		this._dailyChallenge = byte.readUint16();
		this._dailyReelBuy = byte.readUint16();
		//宠物站位<id, 位置>
		{
			const len = byte.readUint16();
			for (let i = 0; i < len; i++) {
				const k = byte.readUint32();
				const v = byte.readInt8();
				this._pet.put(k, v);
			}
		}
		//挑战记录<赛季时间, 记录>
		{
			const len = byte.readUint16();
			for (let i = 0; i < len; i++) {
				const k = byte.readLongNumber();
				const v = ArenaBattleHistory.create();
				v.fromBytes(byte);
				this._history.put(k, v);
			}
		}
		this._lastRefreshTime = byte.readLongNumber();
		//可挑战的玩家<player_id, >
		{
			const len = byte.readUint16();
			for (let i = 0; i < len; i++) {
				const k = byte.readLongNumber();
				const v = ArenaRankPlayer.create();
				v.fromBytes(byte);
				this._enemy.put(k, v);
			}
		}
		//排名奖励<赛季时间，奖励内容>
		{
			const len = byte.readUint16();
			for (let i = 0; i < len; i++) {
				const k = byte.readLongNumber();
				const v = ArenaRankReward.create();
				v.fromBytes(byte);
				this._rankReward.put(k, v);
			}
		}
		this._rankIndex = byte.readInt32();
		return this;
	}


	/**克隆*/
	public clone(): Arena {
		const byte = Byte.createFromPool();
		this.toBytes(byte);
		byte.pos = 0;
		const clonev = Arena.create().fromBytes(byte);
		Byte.recoverToPool(byte);
		return clonev;
	}


	/**处理更新*/
	public processUpdate(jsonv: string): void {
		if (!jsonv) {
			return;
		}

		const eventID = Arena.EVENT_ID;
		const us = JSON.parse(jsonv);

		for (let i = 0, len = us.length; i < len;) {
			const idx = us[i];
			//参与竞技
			if (idx === E_Arena.JOIN) {
				const oldv = this._join;
				this._join = us[i + 1];
				IAsync.dispatch(eventID, idx, this._join, oldv);
				i += 2;
				continue;
			}
			//参与的竞技场开启时间
			if (idx === E_Arena.JOIN_RANK_START_TIME) {
				const oldv = this._joinRankStartTime;
				this._joinRankStartTime = us[i + 1];
				IAsync.dispatch(eventID, idx, this._joinRankStartTime, oldv);
				i += 2;
				continue;
			}
			//积分
			if (idx === E_Arena.ARENA_SCORE) {
				const oldv = this._arenaScore;
				this._arenaScore = us[i + 1];
				IAsync.dispatch(eventID, idx, this._arenaScore, oldv);
				i += 2;
				continue;
			}
			//本赛季主动挑战次数
			if (idx === E_Arena.CHALLENGE_ACTIVE) {
				const oldv = this._challengeActive;
				this._challengeActive = us[i + 1];
				IAsync.dispatch(eventID, idx, this._challengeActive, oldv);
				i += 2;
				continue;
			}
			//本赛季被动挑战次数
			if (idx === E_Arena.CHALLENGE_NATIVE) {
				const oldv = this._challengeNative;
				this._challengeNative = us[i + 1];
				IAsync.dispatch(eventID, idx, this._challengeNative, oldv);
				i += 2;
				continue;
			}
			//今日第一次处理时间
			if (idx === E_Arena.DAILY_FIRST_TIME) {
				const oldv = this._dailyFirstTime;
				this._dailyFirstTime = us[i + 1];
				IAsync.dispatch(eventID, idx, this._dailyFirstTime, oldv);
				i += 2;
				continue;
			}
			//今日挑战次数
			if (idx === E_Arena.DAILY_CHALLENGE) {
				const oldv = this._dailyChallenge;
				this._dailyChallenge = us[i + 1];
				IAsync.dispatch(eventID, idx, this._dailyChallenge, oldv);
				i += 2;
				continue;
			}
			//今日卷轴已购买数
			if (idx === E_Arena.DAILY_REEL_BUY) {
				const oldv = this._dailyReelBuy;
				this._dailyReelBuy = us[i + 1];
				IAsync.dispatch(eventID, idx, this._dailyReelBuy, oldv);
				i += 2;
				continue;
			}

			//宠物站位<id, 位置>
			if (idx === E_Arena.PET) {
				const k: number = us[i + 1];
				const newv :number = us[i + 2];
				const oldv = this.putPet(k, newv);
				IAsync.dispatch(eventID, idx, k, newv, oldv);
				i += 3;
				continue;
			}

			//挑战记录<赛季时间, 记录>
			if (idx === E_Arena.HISTORY) {
				const k: number = us[i + 1];
				const ctrl: number = us[i + 2];
				if (ctrl === 0) {
					const oldv = this.removeHistory(k);
					if (oldv) {
						oldv.destroy()
					}
				}
				else if (ctrl === 1) {
					const newv = ArenaBattleHistory.create(us[i + 3]);
					const oldv = this.putHistory(k, newv);
					if (oldv) {
						oldv.destroy()
					}
				}
				else {
					const curv = this.getHistory(k);
					if (curv) {
						curv.processUpdate(us[i + 3]);
					}
					else {
						console.error('Arena ArenaBattleHistory is not exist when update! k = ' + k);
					}
				}
				IAsync.dispatch(eventID, idx, k, ctrl);
				i += ctrl === 0 ? 3 : 4;
				continue;
			}
			//上一次手动刷新时间
			if (idx === E_Arena.LAST_REFRESH_TIME) {
				const oldv = this._lastRefreshTime;
				this._lastRefreshTime = us[i + 1];
				IAsync.dispatch(eventID, idx, this._lastRefreshTime, oldv);
				i += 2;
				continue;
			}

			//可挑战的玩家<player_id, >
			if (idx === E_Arena.ENEMY) {
				const k: number = us[i + 1];
				const ctrl: number = us[i + 2];
				if (ctrl === 0) {
					const oldv = this.removeEnemy(k);
					if (oldv) {
						oldv.destroy()
					}
				}
				else if (ctrl === 1) {
					const newv = ArenaRankPlayer.create(us[i + 3]);
					const oldv = this.putEnemy(k, newv);
					if (oldv) {
						oldv.destroy()
					}
				}
				else {
					const curv = this.getEnemy(k);
					if (curv) {
						curv.processUpdate(us[i + 3]);
					}
					else {
						console.error('Arena ArenaRankPlayer is not exist when update! k = ' + k);
					}
				}
				IAsync.dispatch(eventID, idx, k, ctrl);
				i += ctrl === 0 ? 3 : 4;
				continue;
			}

			//排名奖励<赛季时间，奖励内容>
			if (idx === E_Arena.RANK_REWARD) {
				const k: number = us[i + 1];
				const ctrl: number = us[i + 2];
				if (ctrl === 0) {
					const oldv = this.removeRankReward(k);
					if (oldv) {
						oldv.destroy()
					}
				}
				else if (ctrl === 1) {
					const newv = ArenaRankReward.create(us[i + 3]);
					const oldv = this.putRankReward(k, newv);
					if (oldv) {
						oldv.destroy()
					}
				}
				else {
					const curv = this.getRankReward(k);
					if (curv) {
						curv.processUpdate(us[i + 3]);
					}
					else {
						console.error('Arena ArenaRankReward is not exist when update! k = ' + k);
					}
				}
				IAsync.dispatch(eventID, idx, k, ctrl);
				i += ctrl === 0 ? 3 : 4;
				continue;
			}
			//排名
			if (idx === E_Arena.RANK_INDEX) {
				const oldv = this._rankIndex;
				this._rankIndex = us[i + 1];
				IAsync.dispatch(eventID, idx, this._rankIndex, oldv);
				i += 2;
				continue;
			}

			console.error('[Struct Data] can not find enum in Arena with idx = ' + idx + ', version maybe wrong.')
		}

		//全更事件
		ITimer.callLater(this, this.dispatchTotalUpdate);
	}


	/**比对不一致结果*/
	public getCompareInfo(other: Arena): string {
		if (!other) {
			return null;
		}

		const updates: any[] = [];

		if (this._join !== other._join) {
			updates.push(E_Arena.JOIN, this._join);
		}
		if (this._joinRankStartTime !== other._joinRankStartTime) {
			updates.push(E_Arena.JOIN_RANK_START_TIME, this._joinRankStartTime);
		}
		if (this._arenaScore !== other._arenaScore) {
			updates.push(E_Arena.ARENA_SCORE, this._arenaScore);
		}
		if (this._challengeActive !== other._challengeActive) {
			updates.push(E_Arena.CHALLENGE_ACTIVE, this._challengeActive);
		}
		if (this._challengeNative !== other._challengeNative) {
			updates.push(E_Arena.CHALLENGE_NATIVE, this._challengeNative);
		}
		if (this._dailyFirstTime !== other._dailyFirstTime) {
			updates.push(E_Arena.DAILY_FIRST_TIME, this._dailyFirstTime);
		}
		if (this._dailyChallenge !== other._dailyChallenge) {
			updates.push(E_Arena.DAILY_CHALLENGE, this._dailyChallenge);
		}
		if (this._dailyReelBuy !== other._dailyReelBuy) {
			updates.push(E_Arena.DAILY_REEL_BUY, this._dailyReelBuy);
		}

		//宠物站位<id, 位置>
		{
			const idx = E_Arena.PET;
			const ks1 = this._pet.getKeys();
			const ks2 = other._pet.getKeys();
			const vs1 = this._pet.getValues();
			const vs2 = other._pet.getValues();
			const rs = MathUtils.intersectSortedArray(ks1, ks2, vs1, vs2);
			if (rs[0].length > 0) {
				const list = rs[0];
				for (let i = 0, len = list.length; i < len; i++) {
					const k = list[i];
					const newv = this.getPet(k);
					updates.push(idx, k, newv);
				}
			}
			if (rs[1].length > 0) {
				const list = rs[1];
				for (let i = 0, len = list.length; i < len; i++) {
					const k = list[i];
					const newv = this.getPet(k);
					updates.push(idx, k, newv);
				}
			}
			if (rs[2].length > 0) {
				const list = rs[2];
				for (let i = 0, len = list.length; i < len; i++) {
					updates.push(idx, list[i], 0);
				}
			}
		}

		//挑战记录<赛季时间, 记录>
		{
			const idx = E_Arena.HISTORY;
			const ks1 = this._history.getKeys();
			const ks2 = other._history.getKeys();
			const rs = MathUtils.intersectSortedArray(ks1, ks2);
			if (rs[0].length > 0) {
				const list = rs[0];
				for (let i = 0, len = list.length; i < len; i++) {
					const k = list[i];
					const newv = this.getHistory(k);
					const oldv = other.getHistory(k);
					const ui = newv.getCompareInfo(oldv);
					if (ui && ui.length > 0) {
						updates.push(idx, k, 2, ui);
					}
				}
			}
			if (rs[1].length > 0) {
				const list = rs[1];
				for (let i = 0, len = list.length; i < len; i++) {
					const k = list[i];
					const newv = this.getHistory(k);
					updates.push(idx, k, 1, newv.stringify(false));
				}
			}
			if (rs[2].length > 0) {
				const list = rs[2];
				for (let i = 0, len = list.length; i < len; i++) {
					updates.push(idx, list[i], 0);
				}
			}
		}
		if (this._lastRefreshTime !== other._lastRefreshTime) {
			updates.push(E_Arena.LAST_REFRESH_TIME, this._lastRefreshTime);
		}

		//可挑战的玩家<player_id, >
		{
			const idx = E_Arena.ENEMY;
			const ks1 = this._enemy.getKeys();
			const ks2 = other._enemy.getKeys();
			const rs = MathUtils.intersectSortedArray(ks1, ks2);
			if (rs[0].length > 0) {
				const list = rs[0];
				for (let i = 0, len = list.length; i < len; i++) {
					const k = list[i];
					const newv = this.getEnemy(k);
					const oldv = other.getEnemy(k);
					const ui = newv.getCompareInfo(oldv);
					if (ui && ui.length > 0) {
						updates.push(idx, k, 2, ui);
					}
				}
			}
			if (rs[1].length > 0) {
				const list = rs[1];
				for (let i = 0, len = list.length; i < len; i++) {
					const k = list[i];
					const newv = this.getEnemy(k);
					updates.push(idx, k, 1, newv.stringify(false));
				}
			}
			if (rs[2].length > 0) {
				const list = rs[2];
				for (let i = 0, len = list.length; i < len; i++) {
					updates.push(idx, list[i], 0);
				}
			}
		}

		//排名奖励<赛季时间，奖励内容>
		{
			const idx = E_Arena.RANK_REWARD;
			const ks1 = this._rankReward.getKeys();
			const ks2 = other._rankReward.getKeys();
			const rs = MathUtils.intersectSortedArray(ks1, ks2);
			if (rs[0].length > 0) {
				const list = rs[0];
				for (let i = 0, len = list.length; i < len; i++) {
					const k = list[i];
					const newv = this.getRankReward(k);
					const oldv = other.getRankReward(k);
					const ui = newv.getCompareInfo(oldv);
					if (ui && ui.length > 0) {
						updates.push(idx, k, 2, ui);
					}
				}
			}
			if (rs[1].length > 0) {
				const list = rs[1];
				for (let i = 0, len = list.length; i < len; i++) {
					const k = list[i];
					const newv = this.getRankReward(k);
					updates.push(idx, k, 1, newv.stringify(false));
				}
			}
			if (rs[2].length > 0) {
				const list = rs[2];
				for (let i = 0, len = list.length; i < len; i++) {
					updates.push(idx, list[i], 0);
				}
			}
		}
		if (this._rankIndex !== other._rankIndex) {
			updates.push(E_Arena.RANK_INDEX, this._rankIndex);
		}

		const jsonv = updates.length === 0 ? null : JSON.stringify(updates);
		return jsonv;
	}


	/**全部更新*/
	protected dispatchTotalUpdate(): void {
		IAsync.dispatch(Arena.TOTAL_EVENT_ID, this.getV(0));
	}

}
